#include "core.h"
#include "IString.h"

CONST_PCHAR ENC_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define WHITE_CHAR(tested_char) ((UCHAR)tested_char <= ' ')
#define IS_CHARACTER(tested_char) (((tested_char >= 'a') && (tested_char <= 'z')) || ((tested_char >= 'A') && (tested_char <= 'Z')))

#pragma unmanaged 
// ....................................................................................................................
// Konstruktor
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(void) {
	Value = NULL; Length = Capacity = 0; UserData = NULL;
}
// ....................................................................................................................
// ....................................................................................................................
// Destruktor
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::~IString(void) {
	Clear(); // Uvolnim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Uvolnenie objektu z pamate
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Clear(void) {
	if (Value != NULL) delete Value; // Uvolnim pamat
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializujem
}
// ....................................................................................................................
// ....................................................................................................................
// Skratenie obsahu
// Vstup:
//			pLength - nova pozadovana dlzka
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Truncate(INT32 pLength) {
	if (!ICore::IsValidIndex(pLength, 0, Length)) return; // Test validity
	Value[pLength] = 0; // Skratim retazec
	Length = pLength; // Ulozim novu dlzku
}
// ....................................................................................................................
// ....................................................................................................................
// Alokacia pamate podla potreby
// Vstup:
//			pCapacity - nova pozadovana kapacita
//			pCopy - priznak skopirovania aktualneho obsahu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Allocate(INT32 pCapacity, bool pCopy) {
	if (Capacity >= pCapacity) return; // Treba alokovat?
	Capacity = pCapacity; // Ulozim novu kapacitu
	PCHAR NW = new CHAR[ALIGN(Capacity + 4)]; // Alokujem novu pamat
	if (Value != NULL) { // Je alokovana pamat?
		if ((Length > 0) && (pCopy)) memcpy(NW, Value, ALIGN(Length)); // Skopirujem aktualny obsah ak je taka poziadavka
		delete Value; // Zrusim aktualnu pamat
	}
	Value = NW; // Ulozim novy smernik
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(CONST_PCHAR pValue) {
	INT32 L = pValue == NULL ? 0 : (INT32)strlen(pValue); // Vypocitam dlzku vstupu
	SetValue(pValue, L); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
//			pLength - dlzka vstupu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(CONST_PCHAR pValue, INT32 pLength) {
	if (pLength == 0) Truncate(); // Prazdny vstup?
	else { 
		Allocate(pLength, false); // Alokujem pamat
		memcpy(Value, pValue, ALIGN(pLength)); // Skopirujem vstup
		Value[pLength] = 0; Length = pLength; // Ukoncim retazec a ulozim dlzku
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(IString* pValue) {
	if (pValue == NULL) SetValue((PCHAR)NULL, 0); // Neplatny vstup?
	else SetValue(pValue->Value, pValue->Length); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(IString& pValue) {
	SetValue(pValue.Value, pValue.Length); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(CONST_PCHAR pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
//			pLength - dlzka vstupu
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(CONST_PCHAR pValue, INT32 pLength) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue, pLength); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(IString* pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(IString& pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (CONST_PCHAR pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (IString* pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (IString& pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie hodnoty ako char*
// Vstup:
//			Ziaden
// Vystup:
//			aktualna hodnota ako char*
// ....................................................................................................................
PCHAR __fastcall IString::PChar(void) {
	return Length == 0 ? (PCHAR)"" : Value;
}
// ....................................................................................................................
// ....................................................................................................................
// Porovnanie obsahu
// Vstup:
//			pValue - hodnota na porovnanie
//			pStart - zaciatok porovnania
//			pValue - maximalna dlzka porovnania
// Vystup:
//			podla vysledku porovnania
// ....................................................................................................................
INT32 __fastcall IString::Compare(CONST_PCHAR pValue, INT32 pStart, INT32 pLength) {
	if (pLength == -1) return strcmp(PChar() + pStart, pValue == NULL ? "" : pValue); // Porovnam
	return strncmp(PChar() + pStart, pValue == NULL ? "" : pValue, pLength); // Porovnam
}
// ....................................................................................................................
// ....................................................................................................................
// Porovnanie obsahu
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			podla vysledku porovnania
// ....................................................................................................................
INT32 __fastcall IString::Compare(IString* pValue) {
	if (pValue == NULL) return Compare((PCHAR)NULL); // Volam porovnania
	return Compare(pValue->PChar());
}
// ....................................................................................................................
// ....................................................................................................................
// Porovnanie obsahu
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			podla vysledku porovnania
// ....................................................................................................................
INT32 __fastcall IString::Compare(IString& pValue) {
	return Compare(pValue.PChar()); // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Porovnanie obsahu bez ohladu na velkost pismen
// Vstup:
//			pValue - hodnota na porovnanie
//			pStart - zaciatok porovnania
//			pValue - maximalna dlzka porovnania
// Vystup:
//			podla vysledku porovnania
// ....................................................................................................................
INT32 __fastcall IString::CaseCompare(CONST_PCHAR pValue, INT32 pStart, INT32 pLength) {
	if (pLength == -1) return stricmp(PChar() + pStart, pValue == NULL ? "" : pValue); // Porovnam
	return strnicmp(PChar() + pStart, pValue == NULL ? "" : pValue, pLength); // Porovnam
}
// ....................................................................................................................
// ....................................................................................................................
// Porovnanie obsahu bez ohladu na velkost pismen
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			podla vysledku porovnania
// ....................................................................................................................
INT32 __fastcall IString::CaseCompare(IString* pValue) {
	if (pValue == NULL) return CaseCompare((PCHAR)NULL); // Volam porovnania
	return CaseCompare(pValue->PChar());
}
// ....................................................................................................................
// ....................................................................................................................
// Porovnanie obsahu bez ohladu na velkost pismen
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			podla vysledku porovnania
// ....................................................................................................................
INT32 __fastcall IString::CaseCompare(IString& pValue) {
	return CaseCompare(pValue.PChar()); // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Operator ==
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::operator == (CONST_PCHAR pValue) {
	return Compare(pValue) == 0; // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Operator ==
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::operator == (IString* pValue) {
	return Compare(pValue) == 0; // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Operator ==
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::operator == (IString& pValue) {
	return Compare(pValue) == 0; // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Operator !=
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::operator != (CONST_PCHAR pValue) {
	return Compare(pValue) != 0; // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Operator !=
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::operator != (IString* pValue) {
	return Compare(pValue) != 0; // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Operator !=
// Vstup:
//			pValue - hodnota na porovnanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::operator != (IString& pValue) {
	return Compare(pValue) != 0; // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Hladanie prveho vyskytu znaku
// Vstup:
//			pValue - znak pre vyhladanie
//			pStart - zaciatok hladania
// Vystup:
//			pozicia alebo -1
// ....................................................................................................................
INT32 __fastcall IString::FindChar(CHAR pValue, INT32 pStart) {
	if (!ICore::IsValidIndex(pStart, 0, Length)) return -1; // Validacia zaciatku
	PCHAR P = strchr(PChar() + pStart, pValue); // Hladam znak
	return P == NULL ? -1 : (INT32)(P - Value); // Vratim index
}
// ....................................................................................................................
// ....................................................................................................................
// Hladanie prveho vyskytu znaku reverznym smerom
// Vstup:
//			pValue - znak pre vyhladanie
//			pStart - zaciatok hladania
// Vystup:
//			pozicia alebo -1
// ....................................................................................................................
INT32 __fastcall IString::ReverseFindChar(CHAR pValue, INT32 pStart) {
	INT32 S = pStart == -1 ? Length - 1 : pStart; // Urcim zaciatok
	if (!ICore::IsValidIndex(S, 0, Length)) return -1; // Validacia zaciatku
	PCHAR P = Value + S; // Urcim smernik
	while(P >= Value) {
		if (*P-- == pValue) return (INT32)(P - Value + 1); // Prehladavam
	}
	return -1; // Nic som nenasiel
}
// ....................................................................................................................
// ....................................................................................................................
// Hladanie prveho vyskytu retazca
// Vstup:
//			pValue - retazec pre vyhladanie
//			pStart - zaciatok hladania
// Vystup:
//			pozicia alebo -1
// ....................................................................................................................
INT32 __fastcall IString::Find(CONST_PCHAR pValue, INT32 pStart) {
	if (!ICore::IsValidIndex(pStart, 0, Length)) return -1; // Validacia zaciatku
	PCHAR P = strstr(PChar() + pStart, pValue); // Hladam 
	return P == NULL ? -1 : (INT32)(P - Value); // Vratim index
}
// ....................................................................................................................
// ....................................................................................................................
// Hladanie prveho vyskytu retazca reverznym smerom
// Vstup:
//			pValue - retazec pre vyhladanie
//			pStart - zaciatok hladania
// Vystup:
//			pozicia alebo -1
// ....................................................................................................................
INT32 __fastcall IString::ReverseFind(CONST_PCHAR pValue, INT32 pStart) {
	INT32 S = pStart == -1 ? Length - 1 : pStart; // Urcim zaciatok
	if (!ICore::IsValidIndex(S, 0, Length)) return -1; // Validacia zaciatku
	
	INT32 L = (INT32)strlen(pValue); // Ziskam dlzku hladaneho retazca
	if (L == 0) return -1;

	CHAR C = *pValue; // Prvy znak

	PCHAR P = Value + S; // Urcim smernik
	while(P >= Value) {
		if (*P == C) {
			if (memcmp(P, pValue, L) == 0) return (INT32)(P - Value); // Provnam
		}
		P--;
	}
	return -1; // Nic som nenasiel
}
// ....................................................................................................................
// ....................................................................................................................
// Extrahovanie podretazca
// Vstup:
//			pStart - zaciatok
//			pLength - dlzka
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall IString::Substring(INT32 pStart, INT32 pLength, IString *Result) {
	Result->Truncate(); // Vynulujem vysledok
	if (!ICore::IsValidIndex(pStart, 0, Length)) return; // Validacia zaciatku
	INT32 L = pStart + pLength > Length ? Length - pStart : pLength; // Urcim dlzku
	Result->SetValue(Value + pStart, L); // Skopirujem podretazec
}
// ....................................................................................................................
// ....................................................................................................................
// Extrahovanie podretazca zlava
// Vstup:
//			pLength - dlzka
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall IString::LeftSubstring(INT32 pLength, IString *Result) {
	Result->Truncate(); // Vynulujem vysledok
	if (!ICore::IsValidIndex(pLength, 1, Length + 1)) return; // Validacia zaciatku
	Result->SetValue(Value, pLength); // Skopirujem podretazec
}
// ....................................................................................................................
// ....................................................................................................................
// Extrahovanie podretazca zprava
// Vstup:
//			pStart - zaciatok
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall IString::RightSubstring(INT32 pStart, IString *Result) {
	Result->Truncate(); // Vynulujem vysledok
	if (!ICore::IsValidIndex(pStart, 0, Length)) return; // Validacia zaciatku
	Result->SetValue(Value + pStart, Length - pStart); // Skopirujem podretazec
}
// ....................................................................................................................
// ....................................................................................................................
// Sformatovanie retazca
// Vstup:
//			pFormatStr - formatovaci retazec
//			... - dalsie parametre
// Vystup:
//			Ziaden
// ....................................................................................................................
void IString::Format(char *pFormatStr, ...) {
	va_list args;
	va_start(args, pFormatStr);
	int L = _vsnprintf(NULL, 0, pFormatStr, args); // Sformatujem a zistim pocet znakov vysledku
	if (L <= 0) Truncate(); // Je chyba alebo vysledok prazdny? Skratim obsah
	else {
		va_end(args);
		va_start(args, pFormatStr);
		Allocate(L + 1, false); // Alokujem pamat
		int L1 = vsprintf(Value, pFormatStr, args); // Este raz naformatujem
		Length = L1; // Ulozim dlzku
		Value[L1] = 0; // Ukoncim vysledok
	}
	va_end(args);
}
// ....................................................................................................................
// ....................................................................................................................
// Pripojenie hodnoty
// Vstup:
//			pValue - hodnota pre pripojenie
//			pLength - dlzka vstupu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Append(CONST_PCHAR pValue, INT32 pLength) {
	if (pLength <= 0) return; // Treba pripajat?
	Allocate(Length + pLength, true); // Alokujem pamat
	memcpy(Value + Length, pValue, ALIGN(pLength)); // Skopirujem vstup
	Length += pLength; Value[Length] = 0; // Ukoncim retazec a upravim dlzku
}
// ....................................................................................................................
// ....................................................................................................................
// Pripojenie hodnoty
// Vstup:
//			pValue - hodnota pre pripojenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Append(CONST_PCHAR pValue) {
	INT32 L = pValue == NULL ? 0 : (INT32)strlen(pValue); // Ziskam dlzku vstupu
	if (L > 0) Append(pValue, L); // Volam pripojenie
}
// ....................................................................................................................
// ....................................................................................................................
// Pripojenie hodnoty
// Vstup:
//			pValue - hodnota pre pripojenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Append(IString* pValue) {
	if ((pValue != NULL) && (pValue->Length > 0)) Append(pValue->Value, pValue->Length); // Volam pripojenie
}
// ....................................................................................................................
// ....................................................................................................................
// Pripojenie hodnoty
// Vstup:
//			pValue - hodnota pre pripojenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Append(IString& pValue) {
	if (pValue.Length > 0) Append(pValue.Value, pValue.Length); // Volam pripojenie
}
// ....................................................................................................................
// ....................................................................................................................
// Pripojenie znaku
// Vstup:
//			pValue - znak pre pripojenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::AppendChar(CHAR pValue) {
	Allocate(Length + 1, true); // Alokujem pamat
	Value[Length++] = pValue; // Ulozim znak
	Value[Length] = 0; // Ukoncim retazec
}
// ....................................................................................................................
// ....................................................................................................................
// Operator +=
// Vstup:
//			pValue - hodnota pre pripojenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator += (CONST_PCHAR pValue) {
	Append(pValue); // Volam pripojenie
	return *this;
}
// ....................................................................................................................
// ....................................................................................................................
// Operator +=
// Vstup:
//			pValue - hodnota pre pripojenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator += (IString* pValue) {
	Append(pValue); // Volam pripojenie
	return *this;
}
// ....................................................................................................................
// ....................................................................................................................
// Operator +=
// Vstup:
//			pValue - hodnota pre pripojenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator += (IString& pValue) {
	Append(pValue); // Volam pripojenie
	return *this;
}
// ....................................................................................................................
// ....................................................................................................................
// Operator +=
// Vstup:
//			pValue - hodnota pre pripojenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator += (CHAR pValue) {
	AppendChar(pValue); // Volam pripojenie
	return *this;
}
// ....................................................................................................................
// ....................................................................................................................
// Pripojenie sformatovaneho retazca
// Vstup:
//			pFormatStr - formatovaci retazec
//			... - dalsie parametre
// Vystup:
//			Ziaden
// ....................................................................................................................
void IString::AppendFormat(char *pFormatStr, ...) {
	va_list args;
	va_start(args, pFormatStr);
	int L = _vsnprintf(NULL, 0, pFormatStr, args); // Sformatujem a zistim pocet znakov vysledku
	if (L > 0) { // Je co pridavat?
		va_end(args);
		va_start(args, pFormatStr);
		Allocate(Length + L + 1, true); // Alokujem pamat
		int L1 = vsprintf(Value + Length, pFormatStr, args); // Este raz naformatujem
		Length += L1; // Ulozim dlzku
		Value[Length] = 0; // Ukoncim vysledok
	}
	va_end(args);
}
// ....................................................................................................................
// ....................................................................................................................
// Zakodovanie retazca pomocou Base64
// Vstup:
//			Ziaden
// Vystup:
//			Result - zakodovany vysledok
// ....................................................................................................................
void __fastcall IString::EncodeStr(IString *Result) {
	Result->Truncate(0); 
	if (Length == 0) return; // Prazdny vstup?

	BYTE CurrData[3];
	Result->Allocate(((Length / 3) + 1) * 4, false); // Alokujem vysledok

	INT32 I = 0;
	BYTE B, B1;
	for (INT32 i = 0; i < Length; ) {

		INT32 i1 = i;
		CurrData[0] = (i1 < Length) ? Value[i1++] : 0; // Zoberiem tri znaky
		CurrData[1] = (i1 < Length) ? Value[i1++] : 0;
		CurrData[2] = (i1 < Length) ? Value[i1++] : 0;

		i1 = i;
		Result->Value[I] = ENC_TABLE[CurrData[0] >> 2]; // Zakodujem do styroch vo vystupe

		I++; i1++;
		B = CurrData[0] & 0x3; B1 = CurrData[1] & 0xf0; B <<= 4; B1 >>= 4; B |= B1;
		Result->Value[I] = ENC_TABLE[B];

		I++; i1++;
		B1 = CurrData[2] & 0xC0; B = CurrData[1] & 0xf; B1 >>= 6; B <<= 2; B |= B1;
		Result->Value[I] = ENC_TABLE[B];

		I++; i1++;
		Result->Value[I] = ENC_TABLE[CurrData[2] & 0x3f];

		I++; i += 3; // Dalsie znaky
	}
	Result->Length = I; Result->Value[I] = 0; // Nastavim dlzku vysledku a ukoncim ho
}
// ....................................................................................................................
// ....................................................................................................................
// Dekodovanie retazca pomocou Base64
// Vstup:
//			Ziaden
// Vystup:
//			Result - dekodovany vysledok
// ....................................................................................................................
void __fastcall IString::DecodeStr(IString *Result) {
	Result->Truncate(0); 
	if (Length == 0) return; // Prazdny vstup?
	if ((Length & 0x3) != 0) return; // Zly vstup?

	Result->Allocate((Length / 4 + 1) * 3, false); // Alokujem vysledok

	BYTE B;
	CHAR C;
	INT32 I = 0;
	for (INT32 i = 0; i < Length; ) {
		
		C = Value[i]; // Dekodujem tri znaky 
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result->Value[I] = B << 2;
		i++;

		C = Value[i];
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result->Value[I] |= (B >> 4);
		Result->Value[I + 1] = (B << 4);
		if (Result->Value[I] == 0) break;
		i++; I++;

		C = Value[i];
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result->Value[I] |= (B >> 2);
		Result->Value[I + 1] = (B << 6);
		if (Result->Value[I] == 0) break;
		i++; I++;

		C = Value[i];
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result->Value[I] |= B;
		if (Result->Value[I] == 0) break;
		i++; I++;
	}

	Result->Length = I; Result->Value[I] = 0; // Nastavim dlzku a ukoncim retazec
}
// ....................................................................................................................
// ....................................................................................................................
// Odstranenie prazdnych znakov zlava
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::LeftTrim(void) {
	if (Length == 0) return; // Prazdny retazec?
	PCHAR P = Value; // Zaciatok hladania
	while(P >= Value) {
		if (!WHITE_CHAR(*P)) break; // Pri prvom neprazdnom znaku prerusim hladanie
		P++;
	}
	Length -= (INT32)(P - Value); // Urcim novu dlzku
	if (Length > 0) memmove(Value, P, ALIGN(Length)); // Ak je co tak skopirujem
	Value[Length] = 0; // Ukoncim retazec
}
// ....................................................................................................................
// ....................................................................................................................
// Odstranenie prazdnych znakov zprava
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::RightTrim(void) {
	if (Length == 0) return; // Prazdny retazec?
	PCHAR P = Value + Length - 1; // Zaciatok hladania
	while(P >= Value) {
		if (!WHITE_CHAR(*P)) break; // Pri prvom neprazdnom znaku prerusim hladanie
		P--;
	}
	*++P = 0; // Ukoncim retazec
	Length = (INT32)(P - Value); // Urcim novu dlzku
}
// ....................................................................................................................
// ....................................................................................................................
// Odstranenie prazdnych znakov zlava aj zprava
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::Trim(void) {
	if (Length == 0) return; // Prazdny retazec?
	PCHAR P = Value + Length - 1; // Zaciatok hladania
	while(P >= Value) {
		if (!WHITE_CHAR(*P)) break; // Pri prvom neprazdnom znaku prerusim hladanie
		P--;
	}
	*++P = 0; // Ukoncim retazec
	Length = (INT32)(P - Value); // Urcim novu dlzku

	if (Length == 0) return; // Prazdny retazec?
	P = Value; // Zaciatok hladania
	while(P >= Value) {
		if (!WHITE_CHAR(*P)) break; // Pri prvom neprazdnom znaku prerusim hladanie
		P++;
	}
	Length -= (INT32)(P - Value); // Urcim novu dlzku
	if (Length > 0) memmove(Value, P, ALIGN(Length)); // Ak je co tak skopirujem
	Value[Length] = 0; // Ukoncim retazec
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod retazca na int32
// Vstup:
//			pValue - retazec na prevod
// Vystup:
//			prevedena hodnota
// ....................................................................................................................
INT32 __fastcall IString::Str2Int32(CONST_PCHAR pValue, INT32 pStart, INT32 pLength) {
	INT32 R;
	if (pLength == -1) return sscanf(pValue + pStart, "%ld", &R) == 1 ? R : 0; // Prevediem
	
	CHAR BUF[68];
	INT32 L = pLength > 64 ? 64 : pLength; // Upravim max. dlzku
	memcpy(BUF, pValue + pStart, L); BUF[L] = 0; // Skopirujem do buffra
	return sscanf(BUF, "%ld", &R) == 1 ? R : 0; // Prevediem
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod retazca na uint32
// Vstup:
//			pValue - retazec na prevod
// Vystup:
//			prevedena hodnota
// ....................................................................................................................
UINT32 __fastcall IString::Str2UInt32(CONST_PCHAR pValue) {
	UINT32 R;
	return sscanf(pValue, "%lu", &R) == 1 ? R : 0; // Prevediem
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod retazca na int64
// Vstup:
//			pValue - retazec na prevod
// Vystup:
//			prevedena hodnota
// ....................................................................................................................
INT64 __fastcall IString::Str2Int64(CONST_PCHAR pValue) {
	INT64 R;
	return sscanf(pValue, "%lld", &R) == 1 ? R : 0; // Prevediem
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod retazca na uint64
// Vstup:
//			pValue - retazec na prevod
// Vystup:
//			prevedena hodnota
// ....................................................................................................................
UINT64 __fastcall IString::Str2UInt64(CONST_PCHAR pValue) {
	UINT64 R;
	return sscanf(pValue, "%llu", &R) == 1 ? R : 0; // Prevediem
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod retazca na double
// Vstup:
//			pValue - retazec na prevod
// Vystup:
//			prevedena hodnota
// ....................................................................................................................
DOUBLE __fastcall IString::Str2Double(CONST_PCHAR pValue) {
	DOUBLE R;
	return sscanf(pValue, "%lf", &R) == 1 ? R : 0; // Prevediem
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(INT32 pValue) {
	CHAR BUF[32];
	IString::Int32ToStr(pValue, BUF); // Volam prevod
	SetValue(BUF); // Volam ulozenie
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(UINT32 pValue) {
	CHAR BUF[32];
	IString::UInt32ToStr(pValue, BUF); // Volam prevod
	SetValue(BUF); // Volam ulozenie
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(INT64 pValue) {
	CHAR BUF[64];
	IString::Int64ToStr(pValue, BUF); // Volam prevod
	SetValue(BUF); // Volam ulozenie
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(UINT64 pValue) {
	CHAR BUF[64];
	IString::UInt64ToStr(pValue, BUF); // Volam prevod
	SetValue(BUF); // Volam ulozenie
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(DOUBLE pValue) {
	CHAR BUF[64];
	IString::DoubleToStr(pValue, BUF); // Volam prevod
	SetValue(BUF); // Volam ulozenie
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod int32 na retazec
// Vstup:
//			pValue - hodnota pre prevod
//			pThousandSeparator - oddelovac tisicok
// Vystup:
//			Result - vysledok prevodu
// ....................................................................................................................
void __fastcall IString::Int32ToStr(INT32 pValue, PCHAR Result, CHAR pThousandSeparator) {
	if (pThousandSeparator == 0) sprintf(Result, "%ld", pValue); // Prevediem
	else { // Prevod aj s oddelenim tisicok
		CHAR BUF[32];
		sprintf(BUF, "%ld", pValue); // Prevediem
		INT32 L = (INT32)strlen(BUF); // Dlzka prevedenej hodnoty
		INT32 C = L - (L / 3)*3; 
		if (C == 0) C = 3; // Upravim

		PCHAR P = Result; PCHAR P1 = BUF;
		while(true) { // Prejdem vsetky znaky
			*P++ = *P1++;
			if (*P1 == 0) break;
			if (--C == 0) {
				C = 3; *P++ = pThousandSeparator;
			}
		}
		*P = 0;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod uint32 na retazec
// Vstup:
//			pValue - hodnota pre prevod
//			pThousandSeparator - oddelovac tisicok
// Vystup:
//			Result - vysledok prevodu
// ....................................................................................................................
void __fastcall IString::UInt32ToStr(UINT32 pValue, PCHAR Result, CHAR pThousandSeparator) {
	if (pThousandSeparator == 0) sprintf(Result, "%lu", pValue); // Prevediem
	else { // Prevod aj s oddelenim tisicok
		CHAR BUF[32];
		sprintf(BUF, "%lu", pValue); // Prevediem
		INT32 L = (INT32)strlen(BUF); // Dlzka prevedenej hodnoty
		INT32 C = L - (L / 3)*3; 
		if (C == 0) C = 3; // Upravim

		PCHAR P = Result; PCHAR P1 = BUF;
		while(true) { // Prejdem vsetky znaky
			*P++ = *P1++;
			if (*P1 == 0) break;
			if (--C == 0) {
				C = 3; *P++ = pThousandSeparator;
			}
		}
		*P = 0;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod int64 na retazec
// Vstup:
//			pValue - hodnota pre prevod
//			pThousandSeparator - oddelovac tisicok
// Vystup:
//			Result - vysledok prevodu
// ....................................................................................................................
void __fastcall IString::Int64ToStr(INT64 pValue, PCHAR Result, CHAR pThousandSeparator) {
	if (pThousandSeparator == 0) sprintf(Result, "%lld", pValue); // Prevediem
	else { // Prevod aj s oddelenim tisicok
		CHAR BUF[64];
		sprintf(BUF, "%lld", pValue); // Prevediem
		INT32 L = (INT32)strlen(BUF); // Dlzka prevedenej hodnoty
		INT32 C = L - (L / 3)*3; 
		if (C == 0) C = 3; // Upravim

		PCHAR P = Result; PCHAR P1 = BUF;
		while(true) { // Prejdem vsetky znaky
			*P++ = *P1++;
			if (*P1 == 0) break;
			if (--C == 0) {
				C = 3; *P++ = pThousandSeparator;
			}
		}
		*P = 0;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod uint64 na retazec
// Vstup:
//			pValue - hodnota pre prevod
//			pThousandSeparator - oddelovac tisicok
// Vystup:
//			Result - vysledok prevodu
// ....................................................................................................................
void __fastcall IString::UInt64ToStr(UINT64 pValue, PCHAR Result, CHAR pThousandSeparator) {
	if (pThousandSeparator == 0) sprintf(Result, "%llu", pValue); // Prevediem
	else { // Prevod aj s oddelenim tisicok
		CHAR BUF[64];
		sprintf(BUF, "%llu", pValue); // Prevediem
		INT32 L = (INT32)strlen(BUF); // Dlzka prevedenej hodnoty
		INT32 C = L - (L / 3)*3; 
		if (C == 0) C = 3; // Upravim

		PCHAR P = Result; PCHAR P1 = BUF;
		while(true) { // Prejdem vsetky znaky
			*P++ = *P1++;
			if (*P1 == 0) break;
			if (--C == 0) {
				C = 3; *P++ = pThousandSeparator;
			}
		}
		*P = 0;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod double na retazec
// Vstup:
//			pValue - hodnota pre prevod
//			pThousandSeparator - oddelovac tisicok
// Vystup:
//			Result - vysledok prevodu
// ....................................................................................................................
void __fastcall IString::DoubleToStr(DOUBLE pValue, PCHAR Result, CHAR pThousandSeparator) {
	if (pThousandSeparator == 0) {
		sprintf(Result, "%.12lf", pValue); // Prevediem
		PCHAR P = Result + strlen(Result) - 1; // Zacitam hladat zbytocne '0'
		while(true) {
			if (*P == '.') { // Narazil som na des. ciarku?
				*P = 0;
				return;
			}
			if (*P != '0') { // Prva nenulova cislica?
				*++P = 0;
				return;
			}
			P--;
		}
	}
	else {
		CHAR BUF[64];
		sprintf(BUF, "%.12lf", pValue); // Prevediem
		PCHAR P = BUF + strlen(BUF) - 1; // Zacitam hladat zbytocne '0'
		while(true) {
			if (*P == '.') { // Narazil som na des. ciarku?
				*P = 0;
				break;
			}
			if (*P == ',') { // Narazil som na des. ciarku?
				*P = 0;
				break;
			}
			if (*P != '0') { // Prva nenulova cislica?
				*++P = 0;
				break;
			}
			P--;
		}

		PCHAR P2 = strchr(BUF, '.');
		if (P2 == NULL) P2 = strchr(BUF, ',');
		INT32 L = P2 == NULL ? (INT32)strlen(BUF) : (INT32)(P2 - BUF); // Dlzka prevedenej hodnoty
		INT32 C = L - (L / 3)*3; 
		if (C == 0) C = 3; // Upravim

		P = Result; PCHAR P1 = BUF;
		while(true) { // Prejdem vsetky znaky
			*P++ = *P1++;
			if (*P1 == 0) break;
			if (*P1 == '.') {
				strcpy(P, P1); // Doplnim zvysok
				return;
			}
			if (*P1 == ',') {
				strcpy(P, P1); // Doplnim zvysok
				return;
			}
			if (--C == 0) {
				C = 3; *P++ = pThousandSeparator;
			}
		}
		*P = 0;

	}
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(INT32 pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(UINT32 pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(INT64 pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(UINT64 pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(DOUBLE pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (INT32 pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (UINT32 pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (INT64 pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (UINT64 pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (DOUBLE pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Test ci je char na zadanej pozicii znakom
// Vstup:
//			pIndex - pozicia
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::IsCharacter(INT32 pIndex) {
	if (!ICore::IsValidIndex(pIndex, 0, Length)) return false; // Test platnosti indexu
	CHAR C = Value[pIndex]; // Ziskam znak
	return IS_CHARACTER(C); // Vratim vysledok testu
}
// ....................................................................................................................
// ....................................................................................................................
// Pripojenie znaku na koniec pokial tam nie je
// Vstup:
//			pValue - znak pre pripojenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::AppendUniqueChar(CHAR pValue) {
	if ((Length == 0) || (Value[Length - 1] != pValue)) AppendChar(pValue); // Otestujem a volam pripojenie
}
// ....................................................................................................................
// ....................................................................................................................
// Zmazanie znaku z konca ak sa rovna zadanemu
// Vstup:
//			pValue - znak pre vymazanie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::DeleteLastChar(CHAR pValue) {
	if ((Length != 0) && (Value[Length - 1] == pValue)) Truncate(Length - 1); // Otestujem a volam skratenie
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie obsahu do suboru
// Vstup:
//			pFileName - nazov suboru
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::SaveToTextFile(CONST_PCHAR pFileName) {
	FILE *F = fopen(pFileName, "wt+"); // Vytvorim subor
	if (F == NULL) return false; // Chyba?

	bool B = true;
	if (Length > 0) { // Je co ukladat?
		fwrite(Value, 1, Length, F); // Zapisem do suboru
		bool B = ferror(F) == 0; // Chyba?
	}
	fclose(F); // Uzatvorim subor
	return B;
}
// ....................................................................................................................
// ....................................................................................................................
// Nacitanie obsahu zo suboru
// Vstup:
//			pFileName - nazov suboru
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::LoadFromTextFile(CONST_PCHAR pFileName) {
	FILE *F = fopen(pFileName, "rt"); // Otvorim subor
	if (F == NULL) return false; // Chyba?

	bool B = true;

	fseek(F, 0L, SEEK_END); // Presuniem sa na koniec
	INT32 L = ftell(F); // Ziskam dlzku
	fseek(F, 0L, SEEK_SET); // Presuniem sa na zaciatok

	if (L == 0) Truncate(0);
	else {
		Allocate(L, false); // Alokujem
		L = (INT32)fread(Value, 1, L, F);
		B = ferror(F) == 0; // Chyba?
		if (B) {
			Length = L; Value[L] = 0; // Ulozim dlzku a ukoncim retazec
		}
	}
	fclose(F); // Uzatvorim subor
	return B;
}
// ....................................................................................................................
// ....................................................................................................................
// Nahradenie vyskytu podretazcov inymi
// Vstup:
//			pFind - retazec pre najdenie
//			pReplace - nahrada
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::ReplaceStr(CONST_PCHAR pFind, CONST_PCHAR pReplace) {
	INT32 L1 = pFind == NULL ? 0 : (INT32)strlen(pFind); // Ziskam velkost 
	if (L1 == 0) return; // Prazdne?
	INT32 L2 = pReplace == NULL ? 0 : (INT32)strlen(pReplace); // Ziskam velkost

	if (L1 == L2) { // Rovnake nahrady?
		PCHAR P = Value;
		while(true) { // Prehladavam
			PCHAR P1 = strstr(P, pFind);
			if (P1 == NULL) return;
			memcpy(P1, pReplace, L2);
			P = P1 + L2;
			continue;
		}
	}

	if (L1 > L2) { // Nahrada je mensia?
		PCHAR P = Value;
		PCHAR P1 = Value;
		while(true) {
			if (*P == 0) {
				Length = (INT32)(P1 - Value);
				*P1 = 0;
				return;
			}
			if (*P != *pFind) {
				*P1++ = *P++;
				continue;
			}
			if (strncmp(P, pFind, L1) != 0) {
				*P1++ = *P++;
				continue;
			}
			if (L2 > 0) {
				memcpy(P1, pReplace, L2);
				P1 += L2;
			}
			P += L1;
		}
	}

	// Nahrada je vacsia
	INT32 Cap = ((Length / L1) + 1) * L2;
	PCHAR NW = new CHAR[ALIGN(Cap + 1)];

	PCHAR P = Value;
	PCHAR P1 = NW;
	while(true) {
		if (*P == 0) {
			Length = (INT32)(P1 - NW);
			*P1 = 0;
			delete Value;
			Value = NW;
			Capacity = Cap;
			return;
		}
		if (*P != *pFind) {
			*P1++ = *P++;
			continue;
		}
		if (strncmp(P, pFind, L1) != 0) {
			*P1++ = *P++;
			continue;
		}
		if (L2 > 0) {
			memcpy(P1, pReplace, L2);
			P1 += L2;
		}
		P += L1;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie hodnoty ako wchar_t*
// Vstup:
//			Ziaden
// Vystup:
//			alokovana pamat a prevedene na wchar_t
// ....................................................................................................................
PWCHAR __fastcall IString::PWChar(void) {
	if (Length == 0) { // Prazdny obsah?
		PWCHAR P = new WCHAR[1];
		*P = 0; // Vytvorim prazdny retazec
		return P;
	}

	INT32 S = (INT32)mbstowcs(NULL, Value, 0); // Ziskam dlzku
	PWCHAR P = new WCHAR[ALIGN(S + 1)]; // Alokujem pamat
	S = (INT32)mbstowcs(P, Value, S + 1); // Prevediem
	P[S] = 0; // Ukoncim

	return P; // Vratim vysledok
}
// ....................................................................................................................
// ....................................................................................................................
// Ziskanie retazca zo zoznamu oddelenych oddelovacom
// Vstup:
//			pIndex - pozadovany podretazec
//			pValue - zoznam retazcov
//			pSeparator - oddelovac
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall IString::GetSubstring(INT32 pIndex, CONST_PCHAR pValue, CHAR pSeparator, IString *Result) {
	Result->Truncate(); // Inicializacia vysledku
	if ((pValue == NULL) || (*pValue == 0)) return; // Prazdny vstup?

	INT32 C = 0; // Pocitadlo retazcov
	PCHAR P = (PCHAR)pValue; // Zaciatok hladania

	while(true) {
		PCHAR P1 = strchr(P, pSeparator);
		if (P1 == NULL) {
			if (pIndex == C) Result->SetValue(P); // Je to pozadovany retazec?
			return; // Koniec
		}

		if (C == pIndex) { // Je to pozadovany retazec?
			Result->SetValue(P, (INT32)(P1 - P));
			return;
		}

		P = P1 + 1; // Dalsi oddelovac
		C++;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Transformacia na lowercase
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::ToLowercase(void) {
	if (Length > 0) strlwr(Value); // Volam prevod
}
// ....................................................................................................................
// ....................................................................................................................
// Vytvorenie ohraniceneho retazca
// Vstup:
//			pLeftBound, pRightBound - hranicne znaky
//			pValue - hodnota
//			pUseBounds - priznak pouzitia hranice
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::CreateBounded(CHAR pLeftBound, CHAR pRightBound, CONST_PCHAR pValue, bool pUseBounds) {
	if (pUseBounds) {
		Truncate(); // Skratim na nulu
		INT32 L = pValue == NULL ? 0 : (INT32)strlen(pValue); // Ziskam velkost vstupu
		Allocate(L + 2, false); // Alokujem pamat
		AppendChar(pLeftBound); // Zaciatok
		Append(pValue, L); // Hodnota
		AppendChar(pRightBound); // Zaciatok
	}
	else SetValue(pValue); // Ulozim normalnym sposobom
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod FILETIME na retazec
// Vstup:
//			pHighPart, pLowPart - hodnota na prevod rozdelena na dve casti
// Vystup:
//			Result
// ....................................................................................................................
void __fastcall IString::FileTimeToStr(UINT32 pHighPart, UINT32 pLowPart, IString *Result) {
	FILETIME FT; FT.dwHighDateTime = pHighPart; FT.dwLowDateTime = pLowPart;
	FILETIME FT1; ::FileTimeToLocalFileTime(&FT, &FT1);
	SYSTEMTIME ST; ::FileTimeToSystemTime(&FT1, &ST); // Prevediem na systemtime
	Result->Format("%2d.%2d.%4d_%2d:%2d:%2d", (UINT32)ST.wDay, (UINT32)ST.wMonth, (UINT32)ST.wYear, (UINT32)ST.wHour, (UINT32)ST.wMinute, (UINT32)ST.wSecond);
	Result->ReplaceChar(' ', '0'); Result->Value[10] = ' '; // Upravim
}
// ....................................................................................................................
// ....................................................................................................................
// Nahradenie vsetkych vyskytov znaku
// Vstup:
//			pOld - znak pre vyhladanie
//			pNew - znak pre nahradenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::ReplaceChar(CHAR pOld, CHAR pNew) {
	if (Length == 0) return; // Prazdny obsah?
	for (PCHAR P = Value; *P != 0; P++) { // Prejdem vsetky znaky
		if (*P == pOld) *P = pNew;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod FILETIME na retazec
// Vstup:
//			pValue - hodnota na prevod
// Vystup:
//			Result
// ....................................................................................................................
void __fastcall IString::FileTimeToStr(PFILETIME pValue, IString *Result) {
	FILETIME FT1; SYSTEMTIME ST;
	Result->Truncate();
	if (::FileTimeToLocalFileTime(pValue, &FT1) == 0) return;
	if (::FileTimeToSystemTime(&FT1, &ST) == 0) return; // Prevediem na systemtime
	Result->Format("%2d.%2d.%4d_%2d:%2d:%2d", (UINT32)ST.wDay, (UINT32)ST.wMonth, (UINT32)ST.wYear, (UINT32)ST.wHour, (UINT32)ST.wMinute, (UINT32)ST.wSecond);
	Result->ReplaceChar(' ', '0'); Result->Value[10] = ' '; // Upravim
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(CONST_PWCHAR pValue) {
	INT32 L = pValue == NULL ? 0 : (INT32)wcslen(pValue); // Ziskam dlzku vstupu
	SetValue(pValue, L); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
//			pLength - dlzka vstupu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(CONST_PWCHAR pValue, INT32 pLength) {
	if (pLength == 0) Truncate(); // Prazdny vstup?
	else { 
		INT32 L = (INT32)wcstombs(NULL, pValue, pLength); // Ziskam dlzku
		Allocate(L, false); // Alokujem pamat
		wcstombs(Value, pValue, pLength); // Prevediem
		Value[L] = 0; Length = L; // Ukoncim retazec a ulozim dlzku
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Operator =
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			objekt
// ....................................................................................................................
IString& __fastcall IString::operator = (CONST_PWCHAR pValue) {
	SetValue(pValue); // Volam ulozenie hodnoty
	return *this; // Vratim objekt
}
// ....................................................................................................................
// ....................................................................................................................
// Test zaciatku retazca na zadanu hodnotu
// Vstup:
//			pValue - hodnota pre otestovanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::StartsWith(CONST_PCHAR pValue) {
	INT32 L = pValue == NULL ? 0 : (INT32)strlen(pValue); // Ziskam dlzku vstupu
	if (L == 0) return false; // Chyba?
	return CaseCompare(pValue, 0, L) == 0; // Volam porovnanie
}
// ....................................................................................................................
// ....................................................................................................................
// Vymazanie casti retazca
// Vstup:
//			pStart - zaciatok
//			pLength - dlzka
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::DeleteSubstring(INT32 pStart, INT32 pLength) {
	if (!ICore::IsValidIndex(pStart, 0, Length)) return; // Zly zaciatok?
	INT32 L = pStart + pLength > Length ? Length - pStart : pLength; // Urcim dlzku
	if (L == Length) Truncate();
	else {
		memmove(Value + pStart, Value + pStart + L, Length - pStart - L); // Presunie pravu stranu retazca
		Length -= L; Value[Length] = 0;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod uint32 na hex retazec
// Vstup:
//			pValue - cislo na prevod
//			pNumsCount - pocet hexa cisiel vo vysledku
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall IString::HexToStr(UINT32 pValue, PCHAR Result, INT32 pNumsCount) {
	CHAR Format[32];
	sprintf(Format, "%%%dX", pNumsCount); // Vytvorim fotmatovaci retazec
	sprintf(Result, Format, pValue); // Sformatujem
	
	PCHAR P = Result;
	while(*P != 0) { // Nahradim vsetky medzery znakom '0'
		if (*P == ' ') *P = '0';
		P++;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Extrahovanie hodnoty parametra
// Vstup:
//			pValue - zoznam parametrov
//			pName - nazov parametra
//			pLineSeparator - oddelovac riadkov
//			pValueSeparator - oddelovac hodnoty
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall IString::GetParamValue(CONST_PCHAR pValue, CONST_PCHAR pName, CHAR pLineSeparator, CHAR pValueSeparator, IString *Result) {
	PCHAR P = (PCHAR)pValue;
	INT32 NameLength = (INT32)strlen(pName); // Dlzka nazvu
	Result->Truncate(); // Inicializujem vysledok

	while(true) {
		PCHAR P1 = strchr(P, pLineSeparator); // Hladam oddelovac riadku
		INT32 L = (P1 == NULL) ? (INT32)strlen(P) : (INT32)(P1 - P); // Ziskam dlzku parametra
		if (L >= NameLength) {
			PCHAR P2 = strchr(P, pValueSeparator);
			INT32 L1 = (P2 == NULL) ? L : (INT32)(P2 - P);
			if (L1 == NameLength) {
				if (strnicmp(P, pName, L1) == 0) {
					Result->SetValue(P2 + 1, L - (INT32)(P2 - P) - 1); // Ulozim vysledok
					return;
				}
			}
		}

		if (P1 == NULL) return;
		P = P1 + 1;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Vykonanie wildcard testu
// Vstup:
//			pValue - hodnota retazca
//			pWildcard - wildcard 
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::WildcardTest(CONST_PCHAR pValue, CONST_PCHAR pWildcard, CHAR pSeparator) {
	CONST_PCHAR cp = NULL;
	CONST_PCHAR mp = NULL;

	while ((*pValue) && (*pWildcard != '*')) {
		if ((*pWildcard != *pValue) && (*pWildcard != '?')) {
			return false;
		}
		pWildcard++;
		pValue++;
	}

	while (*pValue) {
		if (*pWildcard == '*') {
			pWildcard++;
			if ((*pWildcard == 0) || (*pWildcard == pSeparator)) {
				return true;
			}
			mp = pWildcard;
			cp = pValue+1;
		} else if ((*pWildcard == *pValue) || (*pWildcard == '?')) {
			pWildcard++;
			pValue++;
		} else {
			pWildcard = mp;
			pValue = cp++;
		}
	}

	while (*pWildcard == '*') {
		pWildcard++;
	}
	return (*pWildcard == 0) || (*pWildcard == pSeparator);
}
// ....................................................................................................................
// ....................................................................................................................
// Vytvorenie lowercase kopie
// Vstup:
//			pSource - zdroj
//			pDestination - vysledok
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::LowerCaseCopy(CONST_PCHAR pSource, PCHAR pDestination) {
	PCHAR P1 = (PCHAR)pSource;
	PCHAR P2 = pDestination;

	while(true) {
		CHAR C = *P1++;
		if ((C >= 'A') && (C <= 'Z')) C += 'a' - 'A';
		*P2++ = C;
		if (C == 0) return;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Vykonanie multi wildcard testu
// Vstup:
//			pValue - hodnota retazca
//			pWildcard - subor wildcard prvkov
//			pSeparator - oddelovac
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::WildcardsTest(CONST_PCHAR pValue, CONST_PCHAR pWildcards, CHAR pSeparator) {
	PCHAR P = (PCHAR)pWildcards;
	while(true) {
		if (WildcardTest(pValue, P, pSeparator)) return true; // Volam test na aktualnu hondotu
		P = strchr(P, pSeparator);
		if (P == NULL) return false;
		P++;
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod retazca na FILETIME
// Vstup:
//			pValue - retazec na prevod
// Vystup:
//			true / false
//			Result - prevedena hodnota
// ....................................................................................................................
bool __fastcall IString::Str2FILETIME(CONST_PCHAR pValue, PFILETIME Result) {
	SYSTEMTIME ST;
	if (!Str2SYSTEMTIME(pValue, &ST)) return false; // Prevediem na systemtime
	return ::SystemTimeToFileTime(&ST, Result) != 0;
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod retazca na SYSTEMTIME
// Vstup:
//			pValue - retazec na prevod - 'dd.mm.yyyy hh:mm:ss'
// Vystup:
//			true / false
//			Result - prevedena hodnota
// ....................................................................................................................
bool __fastcall IString::Str2SYSTEMTIME(CONST_PCHAR pValue, PSYSTEMTIME Result) {
	PCHAR P = (PCHAR)pValue;
	PCHAR P1;

	P1 = strchr(P, '.'); // Den
	if (P1 == NULL) return false;
	Result->wDay = Str2Int32(P, 0, (INT32)(P1 - P)); P = P1 + 1;
	if ((Result->wDay < 1) || (Result->wDay > 31)) return false;

	P1 = strchr(P, '.'); // Mesiac
	if (P1 == NULL) return false;
	Result->wMonth = Str2Int32(P, 0, (INT32)(P1 - P)); P = P1 + 1;
	if ((Result->wMonth < 1) || (Result->wMonth > 12)) return false;

	P1 = strchr(P, ' '); // Rok
	if (P1 == NULL) return false;
	Result->wYear = Str2Int32(P, 0, (INT32)(P1 - P)); P = P1 + 1;
	if (Result->wYear < 1601) return false;

	P1 = strchr(P, ':'); // Hodina
	if (P1 == NULL) return false;
	Result->wHour = Str2Int32(P, 0, (INT32)(P1 - P)); P = P1 + 1;
	if ((Result->wHour < 0) || (Result->wHour > 23)) return false;

	P1 = strchr(P, ':'); // Minuta
	if (P1 == NULL) return false;
	Result->wMinute = Str2Int32(P, 0, (INT32)(P1 - P)); P = P1 + 1;
	if ((Result->wMinute < 0) || (Result->wMinute > 59)) return false;

	Result->wSecond = Str2Int32(P);
	if ((Result->wSecond < 0) || (Result->wSecond >= 60)) return false;
	
	Result->wMilliseconds = 0; Result->wDayOfWeek = 0;

	return true; // Prevod prebehol v poriadku
}
// ....................................................................................................................
// ....................................................................................................................
// Test platneho obsahu ako int32
// Vstup:
//			pValue - hodnota na otestovanie
//			pCanBeNegative - povolenie zaporneho cisla
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::IsValidINT32(CONST_PCHAR pValue, bool pCanBeNegative) {
	INT32 R;
	bool B = sscanf(pValue, "%ld", &R) == 1; // Prevediem
	if (!B) return false; // Chyba?
	if (pCanBeNegative) return true; // Moze byt zaporne?
	return R >= 0; // Vratim priznak nezaporneho cisla
}
// ....................................................................................................................
// ....................................................................................................................
// Test platneho obsahu ako int64
// Vstup:
//			pValue - hodnota na otestovanie
//			pCanBeNegative - povolenie zaporneho cisla
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::IsValidINT64(CONST_PCHAR pValue, bool pCanBeNegative) {
	INT64 R;
	bool B = sscanf(pValue, "%lld", &R) == 1; // Prevediem
	if (!B) return false; // Chyba?
	if (pCanBeNegative) return true; // Moze byt zaporne?
	return R >= 0; // Vratim priznak nezaporneho cisla
}
// ....................................................................................................................
// ....................................................................................................................
// Test platneho obsahu ako uint32
// Vstup:
//			pValue - hodnota na otestovanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::IsValidUINT32(CONST_PCHAR pValue) {
	UINT32 R;
	return sscanf(pValue, "%lu", &R) == 1; // Prevediem
}
// ....................................................................................................................
// ....................................................................................................................
// Test platneho obsahu ako uint64
// Vstup:
//			pValue - hodnota na otestovanie
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::IsValidUINT64(CONST_PCHAR pValue) {
	UINT64 R;
	return sscanf(pValue, "%llu", &R) == 1; // Prevediem
}
// ....................................................................................................................
// ....................................................................................................................
// Vyber jazykoveho popisu cisla
// Vstup:
//			pValue - cislo
//			pTexts - zoznam retazcov oddelenych pSeparator
//			pSeparator - oddelovac
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall IString::ChooseLangNumberText(INT32 pValue, CONST_PCHAR pTexts, CHAR pSeparator, IString *Result) {
	if (pValue == 1) return IString::GetSubstring(0, pTexts, pSeparator, Result);
	if ((pValue >= 2) && (pValue <= 4)) return IString::GetSubstring(1, pTexts, pSeparator, Result);
	return IString::GetSubstring(2, pTexts, pSeparator, Result);
}
// ....................................................................................................................
// ....................................................................................................................
// Nacitanie riadku z textoveho suboru
// Vstup:
//			pFile - handle suboru
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::ReadLineFromFile(PVOID pFile) {
	Truncate(); // Skratim na nulu
	while(true) {
		INT32 C = fgetc((FILE*)pFile);
		if (C == EOF) return Length > 0;
		if (C == '\n') return true;
		AppendChar((CHAR)C);
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod znaku na velke pismeno
// Vstup:
//			pValue - znak
// Vystup:
//			vysledok
// ....................................................................................................................
CHAR __fastcall IString::ToUpperChar(CHAR pValue) {
	return (pValue >= 'a') && (pValue <= 'z') ? pValue - ('a' - 'A') : pValue;
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(CONST_PWCHAR pValue) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Konstruktor
// Vstup:
//			pValue - hodnota pre ulozenie
//			pLength - dlzka vstupu
// Vystup:
//			Ziaden
// ....................................................................................................................
IString::IString(CONST_PWCHAR pValue, INT32 pLength) {
	Value = NULL; Length = Capacity = 0; UserData = NULL; // Inicializacia
	SetValue(pValue, pLength); // Volam ulozenie hodnoty
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod znaku na male pismeno
// Vstup:
//			pValue - znak
// Vystup:
//			vysledok
// ....................................................................................................................
CHAR __fastcall IString::ToLowerChar(CHAR pValue) {
	return (pValue >= 'A') && (pValue <= 'Z') ? pValue + ('a' - 'A') : pValue;
}
// ....................................................................................................................
// ....................................................................................................................
// Zmazanie znaku z konca
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::DeleteLastChar(void) {
	Truncate(Length - 1);
}
// ....................................................................................................................
// ....................................................................................................................
// Test vyskytu podretazca bez ohladu na velkost pismen
// Vstup:
//			pValue - retazec v ktorom sa hlada
//			pFindStr - retazec ktory sa hlada
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall IString::SubStringTest(CONST_PCHAR pValue, CONST_PCHAR pFindStr) {
	PCHAR P1 = (PCHAR)pValue;
	PCHAR P2 = (PCHAR)pFindStr;

	if (*pValue == 0) return false; // Prazdny retazec pre hladanie?

	CHAR First = *pFindStr; P2++;
	if (First == 0) return true; // Prazdny hladany retazec?
	if ((First >= 'A') && (First <= 'Z')) First += ('a' - 'A');

	while(true) {
		CHAR C = *P1++;
		if (C == 0) return false; // Koniec?
		if ((C >= 'A') && (C <= 'Z')) C += ('a' - 'A');
		if (C != First) continue;

		PCHAR P3 = P1;
		PCHAR P4 = P2;
		while(true) {
			CHAR C3 = *P3++;
			CHAR C4 = *P4++;
			if (C3 == 0) return C4 == 0; // Koniec
			if (C4 == 0) return true; // Koniec

			if ((C3 >= 'A') && (C3 <= 'Z')) C3 += ('a' - 'A');
			if ((C4 >= 'A') && (C4 <= 'Z')) C4 += ('a' - 'A');
			if (C3 != C4) break; // Nie je zhoda?
		}
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Ulozenie hodnoty
// Vstup:
//			pValue - hodnota pre ulozenie
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SetValue(GUID *pValue) {
	WCHAR* wzGuid;
	HRESULT hr = StringFromCLSID(*pValue, &wzGuid);
	if (FAILED(hr)) Truncate(0);
	else {
		SetValue(wzGuid);
		CoTaskMemFree(wzGuid);
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod octed retazca na UINT64
// Vstup:
//			pString - retazec
//			pCharsCount - maximalny pocet znakov
// Vystup:
//			true / false
//			Result - vysledok
// ....................................................................................................................
bool __fastcall IString::Octed2UINT64(CONST_PCHAR pString, INT32 pCharsCount, UINT64 &Result) {
	Result = 0; // Inicializacia vysledku

	INT32 Count = 0; // Pocet spracovanych znakov
	PCHAR P = (PCHAR)pString;
	while(true) {
		CHAR C = *P++; // Ziskam znak
		if (C == 0) return true; // Koniec retazca?

		if (!((C >= '0') && (C <= '7'))) return false; // Chybny?
		Result <<= 3; Result += (UINT64)(C - '0'); // Pripojim

		Count++;
		if (Count == pCharsCount) return true; // Koniec?
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Serializacia dat do retazca
// Vstup:
//			pData - data na serializaciu
//			pLength - pocet bajtov na serializaciu
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::SerializeData(PBYTE pData, INT32 pLength) {
	Truncate(0); 
	if (pLength == 0) return; // Prazdny vstup?

	BYTE CurrData[3];
	Allocate(((pLength / 3) + 1) * 4, false); // Alokujem vysledok

	INT32 I = 0;
	BYTE B, B1;
	for (INT32 i = 0; i < pLength; ) {

		INT32 i1 = i;
		CurrData[0] = (i1 < pLength) ? pData[i1++] : 0; // Zoberiem tri znaky
		CurrData[1] = (i1 < pLength) ? pData[i1++] : 0;
		CurrData[2] = (i1 < pLength) ? pData[i1++] : 0;

		i1 = i;
		Value[I] = ENC_TABLE[CurrData[0] >> 2]; // Zakodujem do styroch vo vystupe

		I++; i1++;
		B = CurrData[0] & 0x3; B1 = CurrData[1] & 0xf0; B <<= 4; B1 >>= 4; B |= B1;
		Value[I] = ENC_TABLE[B];

		I++; i1++;
		B1 = CurrData[2] & 0xC0; B = CurrData[1] & 0xf; B1 >>= 6; B <<= 2; B |= B1;
		Value[I] = ENC_TABLE[B];

		I++; i1++;
		Value[I] = ENC_TABLE[CurrData[2] & 0x3f];

		I++; i += 3; // Dalsie znaky
	}
	Length = I; Value[I] = 0; // Nastavim dlzku vysledku a ukoncim ho
}
// ....................................................................................................................
// ....................................................................................................................
// Deserializacia dat z retazca
// Vstup:
//			pMaxLength - maximum dat na dekodovanie
// Vystup:
//			Pocet dekodovanych bajtov
//			Result - dekodovane data
// ....................................................................................................................
INT32 __fastcall IString::DeserializeData(INT32 pMaxLength, PBYTE Result) {
	if (Length == 0) return 0; // Prazdny vstup?
	if ((Length & 0x3) != 0) return 0; // Zly vstup?

	INT32 Max = pMaxLength - 1;
	//Result->Allocate((Length / 4 + 1) * 3, false); // Alokujem vysledok

	BYTE B;
	CHAR C;
	INT32 I = 0;
	for (INT32 i = 0; i < Length; ) {
		
		C = Value[i]; // Dekodujem tri znaky 
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result[I] = B << 2;
		i++;

		C = Value[i];
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result[I] |= (B >> 4);
		if (I == Max) return I + 1;
		Result[I + 1] = (B << 4);
		//if (Result[I] == 0) break;
		i++; I++;

		C = Value[i];
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result[I] |= (B >> 2);
		if (I == Max) return I + 1;
		Result[I + 1] = (B << 6);
		//if (Result[I] == 0) break;
		i++; I++;

		C = Value[i];
		if (C == '/') B = 0x3f; else if (C == '+') B = 0x3e; else if (C <= '9') B = C - '0' + 52; else if (C < 'a') B = C - 'A'; else B = C - 'a' + 26;
		Result[I] |= B;
		//if (Result[I] == 0) break;
		if (I == Max) return I + 1;
		i++; I++;
	}

	return I + 1; // Vratim pocet dekdovanych bajtov
}
// ....................................................................................................................
// ....................................................................................................................
// Prevod aktualneho obsahu na UTF8 kodovanie
// Vstup:
//			Ziaden
// Vystup:
//			Ziaden
// ....................................................................................................................
void __fastcall IString::ToUTF8(void) {
}
// ....................................................................................................................
